package dgdb2d;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import com.tinkerpop.blueprints.pgm.Element;

/**
 * Abstrakcyjna klasa bazowa opisujaca element grafu (wierzcholek lub krawedz). Implementowany jest interfejs Element
 * standardu Blueprints.
 * 
 * @author Dominik Zielinski, Patryk Chaber
 * @version 0.42
 * 
 */
public abstract class GDBElement implements Element, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5464169362739882274L;
	/**
	 * Identyfikator elementu.
	 */
	private String id;
	/**
	 * Wlasciwosci elementu. Wlasciwosci sa zapisywane w postaci klucz-wartosc.
	 */
	private HashMap<String, String> properties;

	/**
	 * Konstruktor bezparametrowy. Identyfikator elementu jest generowany losowo.
	 */
	public GDBElement() {
		this(UUID.randomUUID().toString());
	}

	/**
	 * Konstruktor inicjalizujacy ID elementu wybrana wartoscia.
	 * 
	 * @param id
	 *            Wybrane ID elementu.
	 */
	public GDBElement(String id) {
		this.id = id;
		this.properties = new HashMap<String, String>();
	}

	/**
	 * Konstruktor wczytujacy wlasciwosci i ID obiektu na podstawie danych zawartych w drzewie XML.
	 * 
	 * @param root
	 *            Korzen drzewa XML.
	 */
	public GDBElement(org.jdom2.Element root) {
		// wczytanie listy wszystkich wlasciwosci
		List<org.jdom2.Element> properties = new ArrayList<org.jdom2.Element>(root.getChild("Properties").getChildren());
		// wczytanie ID elementu
		this.id = root.getAttributeValue("id"); // UUID.fromString(root.getAttributeValue("id"));
		this.properties = new HashMap<String, String>();
		// przepisanie wlasciwosci
		for (int i = 0; i < properties.size(); ++i) {
			this.properties.put(properties.get(i).getAttributeValue("name"),
					properties.get(i).getAttributeValue("value"));
		}
	}

	/**
	 * 
	 * @see com.tinkerpop.blueprints.pgm.Element#getProperty(java.lang.String)
	 */
	@Override
	public Object getProperty(String key) {
		return properties.get(key);
	}

	/**
	 * 
	 * @see com.tinkerpop.blueprints.pgm.Element#getPropertyKeys()
	 */
	@Override
	public Set<String> getPropertyKeys() {
		return properties.keySet();
	}

	/**
	 * 
	 * @see com.tinkerpop.blueprints.pgm.Element#setProperty(java.lang.String, java.lang.Object)
	 */
	@Override
	public void setProperty(String key, Object value) {
		properties.put(key, value.toString());
		save();
	}

	/**
	 * 
	 * @see com.tinkerpop.blueprints.pgm.Element#removeProperty(java.lang.String)
	 */
	@Override
	public Object removeProperty(String key) {
		if (!properties.containsKey(key))
			return null;
		Object r = properties.get(key);
		properties.remove(key);
		save();
		return r;
	}

	/**
	 * 
	 * @see com.tinkerpop.blueprints.pgm.Element#getId()
	 */
	@Override
	public Object getId() {
		return this.id;
	}

	/**
	 * Pobieranie wlasciwosci elementu w formie drzewa XML.
	 * 
	 * @return Drzewo XML zawierajace informacje o wlasciwosciach elementu.
	 */
	protected org.jdom2.Element getPropertiesAsElement() {
		ArrayList<String> tmpList = new ArrayList<String>(properties.keySet());
		org.jdom2.Element tmpElement;
		org.jdom2.Element r = new org.jdom2.Element("Properties");
		for (int i = 0; i < tmpList.size(); ++i) {
			tmpElement = new org.jdom2.Element("Property");
			tmpElement.setAttribute("name", tmpList.get(i));
			tmpElement.setAttribute("value", properties.get(tmpList.get(i)));
			r.addContent(tmpElement);
		}
		return r;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
/*	@Override
	public String toString() {
		String r;
		// typ + id
		r = super.toString() + "\n" + this.id.toString() + "\n";
		// wlasciwosci
		ArrayList<String> tmpList = new ArrayList<String>(properties.keySet());
		for (int i = 0; i < tmpList.size(); ++i) {
			r += tmpList.get(i) + ":" + this.properties.get(tmpList.get(i)) + "\n";
		}
		return r;
	}
*/	
	@Override
	public String toString() {
		String r = ""; 
		if(this instanceof GDBEdge){
			r += "e";
		} else {
			r += "v";
		}
		r += "["+id+"]";
		return r;
	}

	/**
	 * Abstrakcyjna metoda zapisujaca element do dokumentu XML.
	 */
	protected abstract void save();

}
